﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Office.Interop.Excel;

namespace ObjectModel.Excel
{
    public enum ResizeActions
    {
        Truncate,
        Expand,
        Error
    };
    
    public static class RangeExtensions
    {
        public enum DimensionEquality { Equal, NotEqual, Transposed };

        public static DimensionEquality CompareDimensions(this Range range1, Range range2)
        {
            if (range1.Rows.Count == range2.Rows.Count && range1.Columns.Count == range2.Columns.Count)
                return DimensionEquality.Equal;

            else if (range1.Rows.Count == range2.Columns.Count && range1.Columns.Count == range2.Rows.Count)
                return DimensionEquality.Transposed;

            else return DimensionEquality.NotEqual;
        }

        public static Workbook GetWorkbook(this Range range)
        {
            return range.Worksheet.Parent;
        }

        public static string GetAddressWithSheetName(this Range range)
        {
            return new Regex("\\[.*\\]").Replace(range.GetExternalAddress(), "");
        }

        public static string GetExternalAddress(this Range range)
        {
            //object missing = System.Type.Missing;
            bool isExternal = true;

            return range.get_Address(false, false, XlReferenceStyle.xlA1, isExternal);
        }

        public static ResizeActions GetResizeAction(this Range range)
        {
            if (range.Columns.Count == 1 && range.Rows.Count == 1)
            {
                // If the range is a single cell - we can signify that we are happy for it to be updated in the future 
                // by a dynamic or static range with different dimensions
                return ResizeActions.Expand;
            }
            else
            {
                // If not we are saying that we always want the current dimensions regardless of source size
                return ResizeActions.Truncate;
            }
        }

        public static dynamic TransposedValue(this Range range)
        {
            return range.Application.WorksheetFunction.Transpose(range.Value);
        }

        public static dynamic GetValue(this Range range, bool transpose = false, int reqHeight = 0, int reqWidth = 0)
        {
            range = range.ApplySizeConstraints(reqHeight, reqWidth);

            return transpose ? range.TransposedValue() : range.Value;
        }

        static Range ApplySizeConstraints(this Range range, int reqHeight = 0, int reqWidth = 0)
        {
            Worksheet ws = range.Worksheet;
            
            reqHeight = reqHeight > 0 ? reqHeight : range.Rows.Count;
            reqWidth = reqWidth > 0 ? reqWidth : range.Columns.Count;

            return ws.Range[range[1, 1], range[reqHeight, reqWidth]];
        }

		public static bool IsIntersect(this Range range1, Range range2) {
			int startRow1 = range1.Row;
			int endRow1 = range1.Row + range1.Rows.Count - 1;
			int startRow2 = range2.Row;
			int endRow2 = range2.Row + range2.Rows.Count - 1;

			int startCol1 = range1.Column;
			int endCol1 = range1.Column + range1.Columns.Count - 1;
			int startCol2 = range2.Column;
			int endcol2 = range2.Column + range2.Columns.Count - 1;

			if((startCol2 >= startCol1 && startCol2 <= endCol1) || (endcol2 >= startCol1 && endcol2 <= endCol1)) {
				
				if((startRow2 >= startRow1 && startRow2 <= endRow1) || (endRow2 >= startRow1 && endRow2 <= endRow1))
					return true;
			}

			return false;
		}
    }
}
